<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8" />
  <title>Qwen2.5-VL 聊天页面</title>
  <style>
    body { margin: 0; font-family: 'Segoe UI', Arial, sans-serif; background: #f5f6fa; overflow-x: hidden; }
    .container { display: flex; height: 100vh; overflow-x: hidden; }
    .sidebar {
      width: 260px; background: #fff; border-right: 1px solid #eee; display: flex; flex-direction: column; min-width: 200px; max-width: 320px;
    }
    .sidebar .top { padding: 20px; }
    .sidebar button { width: 100%; padding: 10px; margin-bottom: 16px; background: #1677ff; color: #fff; border: none; border-radius: 6px; cursor: pointer; font-size: 16px; }
    .sidebar .history { flex: 1; overflow-y: auto; padding: 0 20px; }
    .sidebar .user { padding: 20px; border-top: 1px solid #eee; display: flex; align-items: center; }
    .sidebar .user-avatar { width: 36px; height: 36px; background: #1677ff; color: #fff; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 20px; margin-right: 10px; }
    .main { flex: 1; display: flex; flex-direction: column; background: #f5f6fa; min-width: 0; }
    .main-header { padding: 40px 0 0 0; text-align: center; }
    .main-header h2 { margin: 0 0 10px 0; font-weight: 500; }
    .chat-window { flex: 1; overflow-y: auto; overflow-x: hidden; padding: 30px 0 0 0; display: flex; flex-direction: column; align-items: center; min-width: 0; }
    .messages { width: 100%; max-width: 700px; min-width: 0; box-sizing: border-box; }
    .message { display: flex; margin-bottom: 18px; min-width: 0; }
    .message.ai { flex-direction: row; }
    .message.user { flex-direction: row-reverse; }
    .message .avatar { width: 36px; height: 36px; background: #1677ff; color: #fff; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 20px; margin: 0 10px; }
    .message .bubble { background: #fff; border-radius: 8px; padding: 12px 18px; max-width: 90vw; width: fit-content; box-shadow: 0 2px 8px #0001; font-size: 16px; word-break: break-word; overflow-wrap: break-word; min-width: 0; }
    .message.user .bubble { background: #1677ff; color: #fff; }
    .input-area { display: flex; align-items: center; padding: 16px 0 16px 0; background: #fff; border-top: 1px solid #eee; gap: 12px; position: relative; min-width: 0; }
    .input-area input[type="text"] { padding: 12px; font-size: 16px; border: 1px solid #eee; border-radius: 6px; outline: none; background: #f8faff; flex: 1 1 0; min-width: 0; }
    .input-area button { padding: 12px 24px; font-size: 16px; background: #1677ff; color: #fff; border: none; border-radius: 6px; cursor: pointer; }
    .file-label { display: flex; align-items: center; justify-content: center; width: 44px; height: 44px; background: #f0f6ff; border-radius: 8px; cursor: pointer; border: 1px solid #e0eaff; margin: 0 4px; transition: background 0.2s; }
    .file-label:hover { background: #e6f0ff; }
    #previewArea img, #previewArea video { max-width: 120px; max-height: 80px; border-radius: 4px; margin-right: 10px; box-shadow: 0 2px 8px #0001; }
    @media (max-width: 900px) {
      .sidebar { width: 60px; min-width: 0; }
      .main-header { padding: 20px 0 0 0; }
      .messages { width: 98vw; max-width: 98vw; }
      .chat-window { padding: 10px 0 0 0; }
      .input-area input[type="text"] { width: 60vw; }
    }
    @media (max-width: 600px) {
      .sidebar { display: none; }
      .messages { width: 100vw; max-width: 100vw; }
      .chat-window { padding: 0; }
      .input-area { padding: 8px 0; }
    }
  </style>
  <!-- 添加本地的 marked 库作为备份 -->
  <script>
    // 简单的 markdown 解析函数，作为 marked 的备份
    function simpleMarkdown(text) {
      if (!text) return '';
      return text
        .replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/\n/g, '<br>')
        .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
        .replace(/\*(.*?)\*/g, '<em>$1</em>')
        .replace(/`(.*?)`/g, '<code>$1</code>');
    }

    // 确保 marked 可用
    window.marked = window.marked || {
      parse: function(text) {
        return simpleMarkdown(text);
      }
    };
  </script>
  <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js@11.7.0/styles/github.min.css">
  <script src="https://cdn.jsdelivr.net/npm/highlight.js@11.7.0/lib/highlight.min.js"></script>
  <script>
    // 配置marked使用highlight.js
    if (window.marked && window.marked.setOptions) {
      marked.setOptions({
        highlight: function(code, lang) {
          if (lang && hljs.getLanguage(lang)) {
            return hljs.highlight(code, { language: lang }).value;
          } else {
            return hljs.highlightAuto(code).value;
          }
        }
      });
    }
  </script>
</head>
<body>
  <div class="container">
    <div class="sidebar">
      <div class="top">
        <button onclick="startNewChat()">开启新对话</button>
      </div>
      <div class="history" id="history">
        <!-- 历史对话列表（可扩展） -->
      </div>
      <div class="user">
        <div class="user-avatar">你</div>
        <span>个人信息</span>
      </div>
    </div>
    <div class="main">
      <div class="main-header">
        <h2>我是 Qwen2.5-VL，很高兴见到你！</h2>
        <div>我可以帮你分析图片、回答问题和写作各种创意内容，请把你的任务交给我吧~</div>
      </div>
      <div class="chat-window" id="chatWindow">
        <div class="messages" id="messages">
          <!-- 聊天消息 -->
        </div>
      </div>
      <div class="input-area">
        <div id="previewArea" style="display:flex;align-items:center;margin-bottom:8px;"></div>
        <input id="inputMsg" type="text" placeholder="发送消息..." onkeydown="if(event.key==='Enter'){sendMessage();}" style="flex:1;" />
        <label for="fileInput" class="file-label" title="上传图片/视频">
          <svg width="24" height="24" fill="#1677ff" viewBox="0 0 24 24"><path d="M12 16.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm6-10h-1.17l-.59-.59A2 2 0 0 0 15 5h-6a2 2 0 0 0-1.41.59L7 6.5H6a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-10a2 2 0 0 0-2-2Zm0 12H6v-7l2.29 2.29a1 1 0 0 0 1.42 0l2.29-2.3 4.29 4.3V18Zm0-3.41-3.29-3.3a1 1 0 0 0-1.42 0l-2.29 2.3-2.29-2.3a1 1 0 0 0-1.42 0L6 14.59V8.5h12ZM6.5 7a.5.5 0 1 1 0-1 .5.5 0 0 1 0 1Z"/></svg>
        </label>
        <input type="file" id="fileInput" accept="image/*,video/*" style="display:none;" />
        <button onclick="sendMessage()">发送</button>
      </div>
    </div>
  </div>
  <script>
    // 聊天消息数据
    let messages = [
      { role: "ai", content: "我是 Qwen2.5-VL，很高兴见到你！" }
    ];

    let multimodal = null; // 用于存储当前上传的多模态内容

    document.getElementById('fileInput').addEventListener('change', function(e) {
      const file = e.target.files[0];
      if (!file) return;
      const formData = new FormData();
      formData.append('file', file);
      fetch('http://127.0.0.1:5000/upload', {
        method: 'POST',
        body: formData
      })
      .then(res => res.json())
      .then(data => {
        multimodal = data;
        // 预览图片/视频
        let previewHtml = '';
        if (data.type === 'image') {
          previewHtml = `<img src="data:${data.mimetype};base64,${data.data}" />`;
        } else if (data.type === 'video') {
          previewHtml = `<video src="data:${data.mimetype};base64,${data.data}" controls></video>`;
        }
        document.getElementById('previewArea').innerHTML = previewHtml;
      })
      .catch(error => {
        console.error('Upload error:', error);
        alert('上传文件失败，请重试');
      });
    });

    function renderMessages() {
      const msgBox = document.getElementById('messages');
      msgBox.innerHTML = '';
      messages.forEach(msg => {
        let contentHtml = '';
        if (msg.role === 'ai') {
          // AI消息用Markdown渲染，如果marked不可用则使用简单解析
          try {
            contentHtml = window.marked.parse(msg.content || '');
          } catch (e) {
            console.warn('Marked parsing failed, using simple markdown:', e);
            contentHtml = simpleMarkdown(msg.content || '');
          }
        } else {
          // 用户消息处理
          if (Array.isArray(msg.content)) {
            // 多模态消息
            msg.content.forEach(item => {
              if (item.type === 'text') {
                contentHtml += `<span>${escapeHtml(item.text || '')}</span>`;
              } else if (item.type === 'image_url') {
                const url = item.image_url.url;
                if (url.startsWith('data:')) {
                  contentHtml += `<img src="${url}" style="max-width: 200px; max-height: 200px; border-radius: 4px; margin: 8px 0;" />`;
                }
              }
            });
          } else {
            // 纯文本消息
            contentHtml = `<span>${escapeHtml(msg.content || '')}</span>`;
          }
        }
        msgBox.innerHTML += `
          <div class="message ${msg.role}">
            <div class="avatar">${msg.role === 'ai' ? '🤖' : '你'}</div>
            <div class="bubble">${contentHtml}</div>
          </div>
        `;
      });
      // 渲染代码高亮
      msgBox.querySelectorAll('pre code').forEach(block => {
        if (window.hljs) {
          hljs.highlightElement(block);
        }
      });
      // 聊天窗口自动滚动到底部
      msgBox.scrollTop = msgBox.scrollHeight;
      const chatWindow = document.getElementById('chatWindow');
      if (chatWindow) chatWindow.scrollTop = chatWindow.scrollHeight;
    }

    function sendMessage() {
      const input = document.getElementById('inputMsg');
      const text = input.value.trim();
      if (!text && !multimodal) return;

      console.log('Sending message:', { text, multimodal }); // 调试日志

      // 构建用户消息
      let userMessage = { role: "user", content: [] };
      
      // 添加文本（如果有）
      if (text) {
        userMessage.content.push({
          type: "text",
          text: text
        });
      }
      
      // 添加图片（如果有）
      if (multimodal && multimodal.type === 'image') {
        userMessage.content.push({
          type: "image_url",
          image_url: {
            url: `data:${multimodal.mimetype};base64,${multimodal.data}`
          }
        });
      }

      messages.push(userMessage);
      renderMessages();
      input.value = '';

      // 先插入一个空的AI消息
      messages.push({ role: "ai", content: "" });
      renderMessages();

      // 构建请求数据
      const requestData = {
        message: text,
        history: messages.slice(0, messages.length - 1),
        multimodal: multimodal
      };

      console.log('Request data:', JSON.stringify(requestData, null, 2)); // 调试日志

      // fetch流式读取
      fetch('http://127.0.0.1:5000/chat', {
        method: 'POST',
        headers: { 
          'Content-Type': 'application/json',
          'Accept': 'text/plain'
        },
        body: JSON.stringify(requestData)
      }).then(response => {
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }
        const reader = response.body.getReader();
        let aiMsg = "";
        function readChunk() {
          reader.read().then(({ done, value }) => {
            if (done) {
              console.log('Stream complete'); // 调试日志
              renderMessages();
              multimodal = null; // 清空多模态内容
              // 清除预览
              document.getElementById('previewArea').innerHTML = '';
              return;
            }
            // 解码流式内容
            const chunk = new TextDecoder().decode(value);
            console.log('Received chunk:', chunk); // 调试日志
            aiMsg += chunk;
            messages[messages.length - 1].content = aiMsg;
            renderMessages();
            readChunk();
          }).catch(error => {
            console.error('Read chunk error:', error); // 调试日志
            messages[messages.length - 1].content = "读取响应时出错，请重试。";
            renderMessages();
          });
        }
        readChunk();
      }).catch(error => {
        console.error('Fetch error:', error); // 调试日志
        messages[messages.length - 1].content = "AI服务异常，请稍后重试。";
        renderMessages();
        multimodal = null;
        // 清除预览
        document.getElementById('previewArea').innerHTML = '';
      });
    }

    function startNewChat() {
      messages = [
        { role: "ai", content: "我是 Qwen2.5-VL，很高兴见到你！" }
      ];
      renderMessages();
    }

    // 防止XSS的简单转义
    function escapeHtml(text) {
      return text.replace(/[&<>"']/g, function (c) {
        return {'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;','\'':'&#39;'}[c];
      });
    }

    // 初始化
    renderMessages();
  </script>
</body>
</html>

